package demo;

import java.io.File;
import java.util.Calendar;
import java.util.Vector;

import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;
import org.artofsolving.jodconverter.process.SigarProcessManager;

public class PDFConverterPool /*implements Runnable*/ {
	
	private static PDFConverterPool instance = null;
	private static OfficeManager officeManager = null;
	public Vector<OfficeDocumentConverter> pool = null; //
	
	//Pool Property
	private int maxConn;
	private int minConn;
	private int refreshMinutes;
	
	public static PDFConverterPool getInstance(){
		if (instance==null || officeManager==null){
			instance = new PDFConverterPool();
			instance.initPool();
		}
		return instance;
	}
	
	public void initPool(){
		createPool();
	}
	
	/**
	 * Create Pool with initial converter.
	 */
	private void createPool() {
		maxConn = 10;
		minConn = 5;
		refreshMinutes=5;
		
		pool = new Vector<OfficeDocumentConverter>();
		
		//One OfficeManager multiple converter connection
		officeManager = initProcessManager();
		OfficeDocumentConverter converter = null;
		for (int i=0;i<minConn;i++){
			converter = getNewConverter(officeManager);
			pool.add(converter);
		}
		
	}
	
	private void destroyPool(){
		if (pool!=null){
			pool.clear();
			pool = null;
			releaseConverter();
		}
	}
	
	/**
	 * Get Converter from Pool.
	 * 
	 * @return OfficeDocumentConverter
	 */
	public synchronized OfficeDocumentConverter getOfficeDocumentConverter() {
		OfficeDocumentConverter converter = null;
		if (pool.size() > 0) {
			converter = (OfficeDocumentConverter) pool.firstElement();
			pool.removeElementAt(0);
			try {
				if (converter == null) {
					converter = getOfficeDocumentConverter();
				}
			} catch (Exception e) {
				converter = getOfficeDocumentConverter();
			}
			if (pool.size() > maxConn) {
				releaseOne();
			}
		} else if ((maxConn == 0) || (pool.size() < maxConn)) {
			officeManager = initProcessManager();
			converter = getNewConverter(officeManager);
		}

		return converter;
	}

	/**
	 * Release Converter to Pool.
	 * 
	 * @param converter
	 *            OfficeDocumentConverter
	 */
	public synchronized void releaseOfficeDocumentConverter(OfficeDocumentConverter converter) {
		try {
			if (converter != null) {
				pool.addElement(converter);
			}
			notifyAll();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private synchronized void releaseOne() {
		if (pool!=null && pool.firstElement() != null) {
			try {
				pool.removeElementAt(0);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private OfficeManager initProcessManager(){
		Long begin=Calendar.getInstance().getTimeInMillis();//LOG
		OfficeManager newOfficeManager = new DefaultOfficeManagerConfiguration().buildOfficeManager();
		Long end=Calendar.getInstance().getTimeInMillis();//LOG			
		System.out.println("Build Office Manager Take millisseconds:"+ (end-begin));//LOG
		
		newOfficeManager.start();
		Long end2=Calendar.getInstance().getTimeInMillis();//LOG			
		System.out.println("Office Manager Start sTake millisseconds:"+ (end-end2));//LOG
		return newOfficeManager;
	}
	
	/**
	 * <b>Caution: In order to use to replace default process manager, more
	 * configuration required for JVM. Now no need to call this method because JOD will auto detect when add this jar.</b><br/>
	 * OOo inter-process communication can use either TCP sockets or named
	 * pipes. The default is to use a TCP socket, on port 2002.<br>
	 * 
	 * Named pipes have the advantage of not taking up TCP ports (with their
	 * potential security implications), and they are marginally faster. However
	 * they require a native library to be loaded by the JVM, and this means
	 * having to set the java.library.path system property. That's why it's not
	 * the default.<br/>
	 * 
	 * The path that needs to be added to java.library.path is different
	 * depending on the platform, but it should be the directory in the OOo
	 * installation containing libjpipe. On Linux it's e.g.:<br/>
	 * 
	 * java -Djava.library.path=/opt/openoffice.org/ure/lib ...<br/>
	 * while on Windows:<br/>
	 * 
	 * java "-Djava.library.path=C:\Program Files\OpenOffice.org 3\URE\bin"
	 * ...</br>
	 */
	@Deprecated
	public void setSigarProcessManager(OfficeManager officeManager) {
		officeManager = new DefaultOfficeManagerConfiguration()
				.setProcessManager(new SigarProcessManager())
				.buildOfficeManager();
	}
	
	private OfficeDocumentConverter getNewConverter(OfficeManager officeManager){
		Long end1=Calendar.getInstance().getTimeInMillis();//LOG			
	    OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
	    Long end2=Calendar.getInstance().getTimeInMillis();//LOG			
	    System.out.println("New OfficeDocumentConverter Take millisseconds:"+ (end2-end1));//LOG
	    return converter;
	}
	
	private void releaseConverter(){
		if (officeManager!=null){
			officeManager.stop();
		}else{
			throw new NullPointerException("Office Manager haven't initialize!");
		}
	}
	
	/**
	 * All conversions supported by OpenOffice.org, including<br/>
	 * 
	 * Microsoft Office to OpenDocument, and viceversa<br/>
	 * Word to OpenDocument Text (odt); OpenDocument Text (odt) to Word<br/>
	 * Excel to OpenDocument Spreadsheet (ods); OpenDocument Spreadsheet (ods)
	 * to Excel<br/>
	 * PowerPoint to OpenDocument Presentation (odp); OpenDocument Presentation
	 * (odp) to PowerPoint<br/>
	 * 
	 * Any format to PDF<br/>
	 * OpenDocument (Text, Spreadsheet, Presentation) to PDF<br/>
	 * Word to PDF; Excel to PDF; PowerPoint to PDF<br/>
	 * RTF to PDF; WordPerfect to PDF; ...<br/>
	 * And more<br/>
	 * 
	 * OpenDocument Presentation (odp) to Flash; PowerPoint to Flash<br/>
	 * RTF to OpenDocument; WordPerfect to OpenDocument<br/>
	 * Any format to HTML (with limitations)<br/>
	 * Support for OpenOffice.org 1.0 and old StarOffice formats<br/>
	 * 
	 * @param source
	 * @param destination
	 */
	public void convertDocumentToPDF(File source, File destination){
		try{
			
		    OfficeDocumentConverter converter = getOfficeDocumentConverter();
		    
		    Long end2=Calendar.getInstance().getTimeInMillis();//LOG			
		    converter.convert(source, destination);
		    Long end3=Calendar.getInstance().getTimeInMillis();//LOG			
		    System.out.println("Convert Take millisseconds:"+ (end3-end2));//LOG
		    
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	/*public void run() {
		while(true){
			
		}
	}*/
	
}
